/**
 * 
 */
package com.google.code.sip.ucenter.ws.provider;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.MessageBodyReader;

import org.apache.commons.beanutils.BeanUtils;

import com.google.code.sip.core.utils.ReflectionUtils;
import com.sun.jersey.core.util.ReaderWriter;

/**
 * @author Liuye
 * 
 */
public class DtoReader<T> implements MessageBodyReader<T> {
	private Class<T> dtoClass;

	public DtoReader() {
		this.dtoClass = ReflectionUtils.getSuperClassGenricType(getClass());
	}

	@Override
	public boolean isReadable(Class<?> type, Type genericType,
			Annotation[] annotations, MediaType mediaType) {
		return type.equals(dtoClass);
	}

	@Override
	public T readFrom(Class<T> type, Type genericType,
			Annotation[] annotations, MediaType mediaType,
			MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
			throws IOException, WebApplicationException {
		final Map<String, String> map = new HashMap<String, String>();
		final String encoded = ReaderWriter.readFromAsString(entityStream,
				mediaType);
		final String charsetName = ReaderWriter.getCharset(mediaType).name();
		final StringTokenizer tokenizer = new StringTokenizer(encoded, "&");
		String token;
		try {
			while (tokenizer.hasMoreTokens()) {
				token = tokenizer.nextToken();
				int idx = token.indexOf('=');
				if (idx < 0) {
					map.put(URLDecoder.decode(token, charsetName), null);
				} else if (idx > 0) {
					map.put(URLDecoder.decode(token.substring(0, idx),
							charsetName), URLDecoder.decode(token
							.substring(idx + 1), charsetName));
				}
			}
			return toDto(map);
		} catch (Exception ex) {
			throw new WebApplicationException(ex, Status.BAD_REQUEST);
		}
	}

	protected T toDto(Map<String, String> map) throws IllegalAccessException,
			InvocationTargetException {
		T entity = instanceDto();
		BeanUtils.copyProperties(entity, map);
		return entity;
	}

	protected T instanceDto() {
		return org.springframework.beans.BeanUtils.instantiate(dtoClass);
	}

}
